﻿using System.Drawing;
using System.IO;

namespace PhoobearLibs.Media.Imaging.WBMP
{    
    /// <summary>
    /// Wireless Bitmap Decoder
    /// WBMP를 일반 비트맵으로 디코딩 합니다.
    /// </summary>
    public sealed class WBMPBitmapDecoder
    {
        public WBMPBitmap Decode(string path)
        {
            WBMPBitmap bitmap = null;

            using(FileStream fs = new FileStream(path, FileMode.Open))
            {
                BufferedStream bs = new BufferedStream(fs);
                bitmap = this.Decode(bs);
            }
            
            return bitmap;
        }

        private bool[] DecodeData(Stream stream, Size size)
        {
            int area = size.Height * size.Width;
            bool[] buffer = new bool[area];

            int pos = 0;
            for (int row = 0; row < size.Height; row++)
            {
                for (int col = 0; col < size.Width; )
                {
                    byte b = (byte)stream.ReadByte();

                    for (int pel = 7; pel >= 0; pel--)
                    {
                        if (col++ < size.Width)
                        {
                            byte mask = (byte)(0x01 << pel);
                            byte pixel = (byte)(b & mask);
                            if (pixel != 0)
                            {
                                buffer[pos] = true;
                            }
                            else
                            {
                                buffer[pos] = false;
                            }
                            pos++;
                        }
                    }
                }
            }

            return buffer;
        }

        public WBMPBitmap Decode(Stream stream)
        {
            int type = ConvertMB(stream);
            if (type != 0)
            {
                return null;
            }

            if (ConvertMB(stream) < 0)
            {
                return null;
            }

            int width = ConvertMB(stream);
            if (width < 0)
            {
                return null;
            }

            int height = ConvertMB(stream);
            if (height < 0)
            {
                return null;
            }

            Size sz = new Size(width, height);

            bool[] bitmap = DecodeData(stream, sz);

            return new WBMPBitmap() { Type = type, Bitmap = bitmap, Size = sz };
        }

        private int ConvertMB(Stream stream)
        {
            int i, mbi = 0;

            while (stream.Position < stream.Length)
            {
                i = stream.ReadByte();
                if (i < 0) return (-1);
                mbi = mbi << 7 | i & 0x7f;
                if ((i & 0x80) == 0)
                {
                    break; 
                }
            }            

            return mbi;
        }

        private bool SkipHeader(Stream stream)
        {
            int i;

            while (stream.Position < stream.Length)
            {
                i = stream.ReadByte();
                if (i < 0)
                    return true;
                if ((i & 0x80) == 0)
                {
                    break;
                }
            }

            return false;
        }


    }
}
